home *** CD-ROM | disk | FTP | other *** search
- library DeskManager;
-
- {---------------------------------------------------------------------
- Name: DeskManager
- Purpose: Provide direct access to the desktop list-view control
- Written by Dave Jewell, 2001 for the Delphi Magazine
- Based on an original idea by Jeffrey Richter.
- -----------------------------------------------------------------------}
-
- uses
- Windows, Messages, CommCtrl, DeskManMessages;
-
- {$R DeskManagerDlg.res}
-
- var
- Hook: HHook = 0; // used for message chaining
- AppWindow: hWnd = 0; // handle of application window
- DeskLV: hWnd = 0; // desktop list-view handle
-
- //------------------------------------------------------------------------------
- // Get a window to the ListView control which implements the desktop
- //------------------------------------------------------------------------------
-
- function DeskManagerListView: HWnd; stdcall; export;
- var
- buff: array [0..255] of Char;
- begin
- if DeskLV = 0 then begin
- DeskLV := GetWindow (GetWindow (FindWindow ('ProgMan', Nil), gw_Child), gw_Child);
- if DeskLV <> 0 then begin
- GetClassName (DeskLV, buff, sizeof (buff));
- if buff <> 'SysListView32' then DeskLV := 0;
- end;
-
- if DeskLV = 0 then MessageBox (0, 'Panic: Desktop ListView control not found', 'DeskManager', mb_OK);
- end;
-
- Result := DeskLV;
- end;
-
- //------------------------------------------------------------------------------
- // Get the thread ID of the Explorer thread which manages the desktop
- //------------------------------------------------------------------------------
-
- function DeskManagerShellThread: DWord; stdcall; export;
- begin
- Result := GetWindowThreadProcessID (DeskManagerListView, Nil);
- end;
-
- //------------------------------------------------------------------------------
- // Redraw all desktop items after changing some metric
- //------------------------------------------------------------------------------
-
- procedure RedrawItems;
- var
- Count: Integer;
- begin
- Count := SendMessage (DeskManagerListView, lvm_GetItemCount, 0, 0);
- SendMessage (DeskManagerListView, lvm_RedrawItems, 0, Count - 1);
- UpdateWindow (DeskManagerListView);
- end;
-
- function HandleGetItemText (DlgWnd: hWnd; Index: Integer): Integer;
- var
- Count: Integer;
- cds: TCopyDataStruct;
- buff: array [0..255] of Char;
- begin
- Result := 0;
- Count := SendMessage (DeskManagerListView, lvm_GetItemCount, 0, 0);
- if (Index >= 0) and (Index < Count) then begin
- buff[0] := #0;
- ListView_GetItemText (DeskManagerListView, Index, 0, buff, sizeof (buff));
- cds.dwData := DM_GetItemText;
- cds.cbData := lstrlen (buff) + 1;
- cds.lpData := @buff;
- Result := SendMessage (AppWindow, wm_CopyData, DlgWnd, Integer (@cds));
- end;
- end;
-
- //------------------------------------------------------------------------------
- // This is the window proc of the hidden desk manager dialog.
- // Runs in Explorer's process context.
- //------------------------------------------------------------------------------
-
- function DeskManDlgProc (DlgWnd: hWnd; Msg, wParam, lParam: Integer): Integer; stdcall;
- begin
- Result := 0;
-
- case Msg of
-
- // -------- Get number of items on the desktop
-
- DM_GetItemCount:
- Result := ListView_GetItemCount (DeskManagerListView);
-
- // -------- Get desktop text colour
-
- DM_GetTextColor:
- Result := SendMessage (DeskManagerListView, LVM_GetTextColor, 0, 0);
-
- // -------- Set desktop text colour: lParam = new color
-
- DM_SetTextColor:
- begin
- Result := SendMessage (DeskManagerListView, lvm_SetTextColor, 0, lParam);
- RedrawItems;
- end;
-
- // -------- Get text of a designated item: wParam = index
-
- DM_GetItemText:
- Result := HandleGetItemText (DlgWnd, wParam);
-
- // -------- Destroy the dialog window
-
- wm_Close:
- DestroyWindow (DlgWnd);
- end;
- end;
-
- //------------------------------------------------------------------------------
- // Implement the message hook. Runs in Explorer's process context
- //------------------------------------------------------------------------------
-
- function GetMsgProc (nCode: Integer; wParam: wParam; lParam: lParam): lParam; stdcall;
- begin
- if Hook = 0 then begin
- Hook := (PMsg (lParam))^.lParam;
- // Create the server window to service client requests
- CreateDialog (hInstance, PChar (101), 0, @DeskManDlgProc);
- // Get application window handle
- AppWindow := (PMsg (lParam))^.wParam;
- // Tell the original application that server is ready
- PostThreadMessage (GetWindowThreadProcessID (AppWindow, Nil), wm_Null, 0, 0);
- end;
-
- Result := CallNextHookEx (Hook, nCode, wParam, lParam);
- end;
-
- //------------------------------------------------------------------------------
- // Initialise and inject the DLL. Runs in the client application context
- //------------------------------------------------------------------------------
-
- function DeskManagerLoad (AppWindow: hWnd): Bool; stdcall; export;
- begin
- Result := False;
- // Various safety checks...
- if (Hook = 0) and (FindWindow (Nil, 'Delphi Desktop 2001') = 0) then begin
- // Hook the desktop thread
- Hook := SetWindowsHookEx (wh_GetMessage, @GetMsgProc, hInstance, DeskManagerShellThread);
- Result := Hook <> 0;
- // If success, post a message to force DLL injection
- if Result then Result := PostThreadMessage (DeskManagerShellThread, wm_Null, AppWindow, Hook);
- end;
- end;
-
- function DeskManagerUnload: Bool; stdcall; export;
- begin
- if Hook <> 0 then Result := UnhookWindowsHookEx (Hook) else Result := False;
- Hook := 0;
- end;
-
-
- exports
- DeskManagerLoad,
- DeskManagerUnload,
- DeskManagerListView,
- DeskManagerShellThread;
-
- begin
- end.
-
- #include "CmnHdr.H"
- #include <Windows.H>
- #include <WindowsX.H>
- #include <CommCtrl.H>
- #include "Resource.H"
-
- static const TCHAR g_szRegSubKey[] = __TEXT ("Software\\Richter\\Desktop Item Position Saver");
-
- void SaveListViewItemPositions(HWND hwndLV)
- {
- int nItem, nMaxItems = ListView_GetItemCount(hwndLV);
- HKEY hkey;
- DWORD dwDisposition;
-
- // When saving new positions, delete the old position
- // information that is currently in the registry.
- RegDeleteKey (HKEY_CURRENT_USER, g_szRegSubKey);
-
- // Create the registry key to hold the info
- RegCreateKeyEx (HKEY_CURRENT_USER, g_szRegSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
-
- for (nItem = 0; nItem < nMaxItems; nItem++)
- {
- TCHAR szName[_MAX_PATH];
- POINT pt;
-
- // Get the name and position of a listview item.
- ListView_GetItemText (hwndLV, nItem, 0, szName, _MAX_PATH);
- ListView_GetItemPosition (hwndLV, nItem, &pt);
-
- // Save the name and position in the registry.
- RegSetValueEx (hkey, szName, 0, REG_BINARY, (PBYTE) &pt, sizeof(pt));
- }
-
- RegCloseKey(hkey);
- }
-
- //--------------------------------------------------------------------------
-
- void RestoreListViewItemPositions (HWND hwndLV)
- {
- HKEY hkey;
- LONG l = RegOpenKeyEx(HKEY_CURRENT_USER, g_szRegSubKey, 0, KEY_QUERY_VALUE, &hkey);
- if (l == ERROR_SUCCESS) {
- int nIndex;
-
- // If the listview has AutoArrange on, temporarily turn it off.
- DWORD dwStyle = GetWindowStyle (hwndLV);
- if (dwStyle & LVS_AUTOARRANGE) SetWindowLong (hwndLV, GWL_STYLE, dwStyle & ~LVS_AUTOARRANGE);
-
- l = NO_ERROR;
- for (nIndex = 0; l != ERROR_NO_MORE_ITEMS; nIndex++) {
- TCHAR szName[_MAX_PATH];
- POINT pt;
- LV_FINDINFO lvfi;
- int cbValueName = _MAX_PATH;
- int cbData = sizeof(pt), nItem;
- DWORD dwType;
-
- // Read a value name and position from the registry.
- l = RegEnumValue(hkey, nIndex, szName, &cbValueName,
- NULL, &dwType, (PBYTE) &pt, &cbData);
-
- if (l == ERROR_NO_MORE_ITEMS) continue;
-
- if ((dwType == REG_BINARY) && (cbData == sizeof(pt))) {
- // The value is something that we recognize; try to find
- // an item in the listview control that matches the name.
- lvfi.flags = LVFI_STRING;
- lvfi.psz = szName;
- nItem = ListView_FindItem(hwndLV, -1, &lvfi);
- if (nItem != -1) ListView_SetItemPosition(hwndLV, nItem, pt.x, pt.y);
- }
- }
- // Turn AutoArrange back on if it was originally on.
- SetWindowLong(hwndLV, GWL_STYLE, dwStyle);
- RegCloseKey(hkey);
- }
- }
-
-
-